package com.cloudlinkin.util;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

/**
 * 配置文件获取工具类
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class PropertiesKit {

	private Logger log = Logger.getLogger(this.getClass());

	private Properties props;
	private URL url;

	public PropertiesKit(Properties props) {
		this.props = props;
	}

	/**
	 * 创建解析工具同时 给如 文件全称 （包含扩展名）
	 * 
	 * @param fileName
	 * @throws IOException
	 */
	public PropertiesKit(String fileName) {
		try {
			props = new Properties();
			ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
			if (classLoader == null) {
				classLoader = this.getClass().getClassLoader();
			}

			synchronized (PropertiesKit.ioLock) {
				try (InputStream in = classLoader.getResourceAsStream(fileName);
						InputStreamReader reader = new InputStreamReader(in, "UTF-8");) {
					props.load(reader);
				}
			}
			url = classLoader.getResource(fileName);
		} catch (Exception e) {
			log.error("#属性文件" + fileName + "加载错误 #", e);
		}
	}

	public void reload(String fileName) throws UnsupportedEncodingException, IOException {
		props = new Properties();
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		if (classLoader == null) {
			classLoader = this.getClass().getClassLoader();
		}

		synchronized (PropertiesKit.ioLock) {
			try (InputStream in = classLoader.getResourceAsStream(fileName);
					InputStreamReader reader = new InputStreamReader(in, "UTF-8");) {
				props.load(reader);
			}
		}
		url = classLoader.getResource(fileName);
	}

	/**
	 * 将指定内容保存为属性文件到本地
	 * 
	 * @param savePath
	 *            文件要保存的路径
	 * @param saveName
	 *            文件保存全称
	 * @param text
	 *            属性文件内容
	 * @throws IOException
	 */
	public PropertiesKit(String savePath, String saveName, String text) throws IOException {
		synchronized (ioLock) {
			props = new Properties();
			synchronized (PropertiesKit.ioLock) {
				try (InputStream in = new ByteArrayInputStream(text.getBytes())) {
					props.load(in);
				}
			}
			File file = new File(savePath);
			if (!file.exists()) {
				file.mkdirs();
			}
			String savaPathName = savePath + "/" + saveName;
			File file2 = new File(savaPathName);
			if (!file2.exists()) {
				file2.createNewFile();
			}
			url = file2.toURI().toURL();
		}
	}

	public Properties get() {
		return props;
	}

	/**
	 * @Title: 获取字符型 不存在返回NULL
	 * @author: 张朋
	 * @date: 2016年11月1日 上午10:00:49
	 * @return: String
	 */
	public String get(String key) {
		String v = props.getProperty(key);
		return StringUtils.isBlank(v) ? null : v;
	}

	/**
	 * @Title: 获取整型 不存在 返回null
	 * @author: 张朋
	 * @date: 2016年11月1日 上午10:00:09
	 * @return: Integer
	 */
	public Integer getInteger(String key) {
		String v = props.getProperty(key);
		return StringUtils.isBlank(v) ? null : Integer.parseInt(v);
	}

	/**
	 * @Title: 获取浮点型 不存在返回null
	 * @author: 张朋
	 * @date: 2016年11月1日 上午10:00:37
	 * @return: double
	 */
	public double getDouble(String key) {
		String v = props.getProperty(key);
		return StringUtils.isBlank(v) ? null : Double.parseDouble(v);
	}

	/**
	 * @Title: 获取布尔类型 不存在返回null
	 * @author: 张朋
	 * @date: 2016年11月1日 上午10:03:18
	 * @return: Boolean
	 */
	public Boolean getBoolean(String key) {
		String v = props.getProperty(key);
		return StringUtils.isBlank(v) ? null : Boolean.parseBoolean(v);
	}

	/**
	 * 获取所有属性，返回一个map,不常用 可以试试props.putAll(t)
	 */
	public Map getAll() {
		Map map = new HashMap();
		for (Iterator<Entry<Object, Object>> iterator = props.entrySet().iterator(); iterator.hasNext();) {
			Entry<Object, Object> next = iterator.next();
			map.put(next.getKey(), next.getValue());
		}
		return map;
	}

	public Map<String, String> getMap() {
		Map map = new HashMap();
		for (Iterator<Entry<Object, Object>> iterator = props.entrySet().iterator(); iterator.hasNext();) {
			Entry<Object, Object> next = iterator.next();
			map.put(next.getKey(), next.getValue());
		}
		return map;
	}

	/**
	 * 在控制台上打印出所有属性，调试时用。
	 */
	public void printAll() {
		props.list(System.out);
	}

	private static Object ioLock = new Object();

	/**
	 * 写入properties信息
	 * 
	 * @throws IOException
	 */
	public void put(String key, String value) throws IOException {

		synchronized (ioLock) {

			OutputStream fos = new FileOutputStream(new File(url.getFile()));

			BufferedOutputStream bos = new BufferedOutputStream(fos);

			props.setProperty(key, value);
			// 将此 Properties 表中的属性列表（键和元素对）写入输出流
			props.store(bos, null);
			bos.flush();
			bos.close();
		}

	}

	/**
	 * 写入properties信息 批量写入
	 * 
	 * @param map
	 *            写入的参数
	 * @param append
	 *            是否追加模式 false直接覆盖整个文件
	 * @throws IOException
	 */
	public void put(Map map, boolean append) throws IOException {

		synchronized (ioLock) {

			if (!append)
				props.clear();

			OutputStream fos = new FileOutputStream(new File(url.getFile()), append);
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			Set keys = map.keySet();
			Iterator<String> ikeys = keys.iterator();
			while (ikeys.hasNext()) {
				// 将此 Properties 表中的属性列表（键和元素对）写入输出流
				String key = ikeys.next();
				String value = (String) map.get(key);
				props.setProperty(key, value);
			}

			props.store(bos, null);
			bos.flush();
			bos.close();
		}
	}
	
	
	
}
